package com.ideal.manage.esms.service.esms;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ideal.manage.esms.bean.esms.EsmsDataBatch;
import com.ideal.manage.esms.jpa.JpaRepositoryImpl;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Service
@Transactional
public class EsmsDataService {
    private Logger LOG = LoggerFactory.getLogger(EsmsDataService.class);

    @Autowired
    private TransportClient transportClient;


    @Autowired
    private EntityManager entityManager;
    private JpaRepositoryImpl<EsmsDataBatch, Long> batchJpaRepository;

    @PostConstruct
    public void init() {
        this.batchJpaRepository = new JpaRepositoryImpl<EsmsDataBatch, Long>(EsmsDataBatch.class, entityManager);
    }


    public void batchInsertMDBS(String projectIp, JSONArray data) throws IOException {
        this.batchInsertData("mdbs", projectIp, data);
    }


    public void batchInsertCANBS(String projectIp, JSONArray data) throws IOException {
        this.batchInsertData("canbs", projectIp, data);
    }

    public void createTodayIndex(String index, String typeName) throws IOException {
        IndicesExistsResponse response = transportClient.admin().indices().prepareExists(index).execute().actionGet();
        if (!response.isExists()) {
            LOG.info("索引{} 不存在", index);
            CreateIndexRequestBuilder createIndexRequestBuilder = transportClient.admin().indices()
                    .prepareCreate(index);

            XContentBuilder mapping = XContentFactory.jsonBuilder()
                    .startObject()
                    .startArray("dynamic_templates")
                    .startObject().field("Cell_").startObject()
                    .field("match", "Cell_*")
                    .field("match_mapping_type", "double")
                    .startObject("mapping").field("type", "double").endObject()
                    .endObject().endObject()
                    .endArray()

                    //properties
                    .startObject("properties")
                    .startObject("2000").field("type", "long").endObject()
                    .startObject("2001").field("type", "long").endObject()
                    .startObject("2002").field("type", "long").endObject()
                    .startObject("2003").field("type", "long").endObject()
                    .startObject("2004").field("type", "long").endObject()
                    .startObject("2005").field("type", "long").endObject()
                    .startObject("2006").field("type", "long").endObject()
                    .startObject("2007").field("type", "long").endObject()
                    .startObject("2008").field("type", "long").endObject()
                    .startObject("2009").field("type", "long").endObject()
                    .startObject("2010").field("type", "long").endObject()
                    .startObject("2011").field("type", "long").endObject()
                    .startObject("2012").field("type", "long").endObject()
                    .startObject("2013").field("type", "long").endObject()
                    .startObject("2014").field("type", "long").endObject()
                    .startObject("2015").field("type", "long").endObject()
                    .startObject("2016").field("type", "long").endObject()
                    .startObject("2017").field("type", "long").endObject()
                    //
                    .startObject("Alarm_AuxFail").field("type", "double").endObject()
                    .startObject("Alarm_BSU_FAULT").field("type", "double").endObject()
                    .startObject("Alarm_BSU_OFFLINE").field("type", "double").endObject()
                    .startObject("Alarm_BatDT").field("type", "double").endObject()
                    .startObject("Alarm_BatDV").field("type", "double").endObject()
                    .startObject("Alarm_BatOC").field("type", "double").endObject()
                    .startObject("Alarm_BatOV").field("type", "double").endObject()
                    .startObject("Alarm_BatUC").field("type", "double").endObject()
                    .startObject("Alarm_BatUV").field("type", "double").endObject()
                    .startObject("Alarm_Bmuil").field("type", "double").endObject()
                    .startObject("Alarm_CellOT").field("type", "double").endObject()
                    .startObject("Alarm_CellOV").field("type", "double").endObject()
                    .startObject("Alarm_CellUT").field("type", "double").endObject()
                    .startObject("Alarm_CellUV").field("type", "double").endObject()
                    .startObject("Alarm_HV_Fail").field("type", "double").endObject()
                    .startObject("Alarm_Hall_Break").field("type", "double").endObject()
                    .startObject("Alarm_LBK").field("type", "double").endObject()
                    .startObject("Alarm_LEAK_OC").field("type", "double").endObject()
                    .startObject("Alarm_PrechrgFail").field("type", "double").endObject()
                    .startObject("Alarm_TBK").field("type", "double").endObject()
                    .startObject("Alarm_Vcu_Offline").field("type", "double").endObject()
                    .startObject("BatAlmLv").field("type", "double").endObject()
                    .startObject("BatCurrent").field("type", "double").endObject()
                    .startObject("BatLife").field("type", "double").endObject()
                    .startObject("BatSoc").field("type", "double").endObject()
                    .startObject("BatSoh").field("type", "double").endObject()
                    .startObject("BatState").field("type", "double").endObject()
                    .startObject("BatVoltage").field("type", "double").endObject()
                    .startObject("CC2St").field("type", "double").endObject()
                    .startObject("CHRG_OCS").field("type", "double").endObject()
                    .startObject("CHRG_OCT").field("type", "double").endObject()
                    .startObject("CcSt").field("type", "double").endObject()
                    .startObject("ChrgReqCurr").field("type", "double").endObject()
                    .startObject("ChrgReqVolt").field("type", "double").endObject()
                    .startObject("ChrgState").field("type", "double").endObject()
                    .startObject("ChrgerOnlineSt").field("type", "double").endObject()
                    .startObject("CoolingCtrl").field("type", "double").endObject()
                    .startObject("DSCH_OCS").field("type", "double").endObject()
                    .startObject("DSCH_OCT").field("type", "double").endObject()
                    .startObject("HeatCtrl").field("type", "double").endObject()
                    .startObject("MainNegaRelay").field("type", "double").endObject()
                    .startObject("MainPosRelay").field("type", "double").endObject()
                    .startObject("MaxAllwChrgCurr").field("type", "double").endObject()
                    .startObject("MaxAllwChrgPwr").field("type", "double").endObject()
                    .startObject("MaxAllwDschCurr").field("type", "double").endObject()
                    .startObject("MaxAllwDschPwr").field("type", "double").endObject()
                    .startObject("MaxCellVolt").field("type", "double").endObject()
                    .startObject("MaxCellVoltNo").field("type", "double").endObject()
                    .startObject("MaxTemp").field("type", "double").endObject()
                    .startObject("MaxTempNo").field("type", "double").endObject()
                    .startObject("MinCellVolt").field("type", "double").endObject()
                    .startObject("MinCellVoltNo").field("type", "double").endObject()
                    .startObject("MinTemp").field("type", "double").endObject()
                    .startObject("MinTempNo").field("type", "double").endObject()
                    .startObject("NonOBCRelay").field("type", "double").endObject()
                    .startObject("OBCRelay").field("type", "double").endObject()
                    .startObject("PrechrgRelay").field("type", "double").endObject()
                    .startObject("data_source").field("type", "keyword").endObject()
                    .startObject("date_time").field("type", "date").field("format", "yyyy-MM-dd HH:mm:ss").endObject()
                    .startObject("id").field("type", "text").endObject()
                    .startObject("ip").field("type", "keyword").endObject()
                    .startObject("macid").field("type", "keyword").endObject()
                    .startObject("messageId").field("type", "keyword").endObject()
                    .startObject("port").field("type", "keyword").endObject()
                    .startObject("time").field("type", "date").field("format", "epoch_millis").endObject()
                    .endObject()

                    //end all
                    .endObject();
            createIndexRequestBuilder.addMapping(typeName, mapping);
            boolean success = createIndexRequestBuilder.get().isShardsAcknowledged();

            LOG.info("创建索引mapping {} {}", mapping.string(), success);
        }
    }

    protected void batchInsertData(String type, String projectIp, JSONArray data) throws IOException {
        if (data.size() == 0) {
            LOG.warn("插入数据为空");
            return;
        }
        JSONObject first = data.getJSONObject(0);
        EsmsDataBatch batch = new EsmsDataBatch();
        batch.setType(type);
        batch.setCreateTime(new Date());
        batch.setDataCount(data.size());
        batch.setProjectIp(projectIp);
        batch.setTime(first.getLong("time"));
        batch.setIntegrationCal(0);
        batchJpaRepository.save(batch);

        String typeName = "mdbs";
        String index = "mdbs-" + new SimpleDateFormat("yyyy.MM.dd").format(new Date());
        this.createTodayIndex(index, typeName);
        BulkRequestBuilder bulkRequest = transportClient.prepareBulk();
        for (int i = 0; i < data.size(); i++) {
            JSONObject jsonObject = data.getJSONObject(i);
            jsonObject.put("id", genBatchId(batch));
            jsonObject.put("ip", projectIp);
            jsonObject.put("data_source", type);
            jsonObject.put("date_time", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(first.getLong("time")));

            bulkRequest.add(transportClient.prepareIndex(index, typeName).setSource(jsonObject.toString(), XContentType.JSON));
        }
        BulkResponse responses = bulkRequest.execute().actionGet();
        if (responses.hasFailures()) {
            throw new RuntimeException(responses.buildFailureMessage());
        }
    }

    private String genBatchId(EsmsDataBatch batch) {
        return String.format("%s_%s", batch.getId(), UUID.randomUUID().toString().replaceAll("-", ""));
    }


}
